home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / BackGround / BackGroundShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  11.9 KB  |  462 lines  |  [TEXT/MPCC]

  1. // Quickdraw 3D sample code
  2. //
  3. // This file illustrates how to set up a pixmap based draw context.
  4. // A metafile is read into and imaged in the pixmap, this pixmap is combined
  5. // with a pixmap containing a background, so that the 3d data is drawn over 
  6. // the background
  7. //
  8. // Nick Thompson, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com)
  9. //
  10. // ©1994-5 Apple Computer Inc., All Rights Reserved
  11.  
  12.  
  13. // system headers
  14. #include <Desk.h>
  15. #include <Dialogs.h>
  16. #include <DiskInit.h>
  17. #include <Fonts.h>
  18. #include <Menus.h>
  19. #include <PictUtil.h>
  20. #include <QDOffScreen.h>
  21. #include <QuickDraw.h>
  22. #include <SegLoad.h>
  23. #include <StandardFile.h>
  24. #include <TextEdit.h>
  25. #include <ToolUtils.h>
  26.  
  27. // for QuickDraw 3D
  28. #include "QD3D.h"
  29. #include "QD3DMath.h"
  30. #include "QD3DDrawContext.h"
  31. #include "QD3DShader.h"
  32. #include "QD3DTransform.h"
  33. #include "QD3DGroup.h"
  34. #include "QD3DCamera.h"
  35.  
  36.  
  37. #include "BackGroundShell.h"
  38. #include "BackGroundSupport.h"
  39.  
  40. // get the interface to my error handler routines
  41. #include "MyErrorHandler.h"
  42.  
  43. const RGBColor    kClearColor = { 0x0000, 0xffff, 0x0000 } ;
  44. const RGBColor    kWhiteColor = { 0xffff, 0xffff, 0xffff } ;
  45.  
  46. //-------------------------------------------------------------------------------------------
  47. // function prototypes
  48.  
  49. static void         InitToolbox( void ) ;
  50. static void         MainEventLoop( void ) ;
  51. static void         HandleKeyPress(EventRecord *event) ;
  52. static void         HandleOSEvent(EventRecord *event) ;
  53. void InitDocumentData( DocumentPtr theDocument ) ;
  54. TQ3Status DocumentDraw3DData( DocumentPtr theDocument ) ;
  55. void DisposeDocumentData( DocumentPtr theDocument) ;
  56. void DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect) ;
  57.  
  58. OSErr WritePict( PicHandle myPic, short  dstPictFRef ) ;
  59. OSErr GetOutputFileRef(short    *dstPictFRef ) ;
  60. PicHandle ImageToPict( DocumentPtr theDocument, WindowPtr theWindow ) ;
  61. void DoSaveAs(DocumentPtr theDocument)  ;
  62.  
  63. //-------------------------------------------------------------------------------------------
  64. //
  65.  
  66. Boolean         gQuitFlag         = false ;
  67. WindowPtr        gMainWindow        = nil ;
  68. DocumentRec        gDocument ;
  69.  
  70. //-------------------------------------------------------------------------------------------
  71. // main()
  72. // entry point for the application, initialize the toolbox, initialize QuickDraw 3D
  73. // and enter the main event loop.  On exit from the main event loop, we want to call
  74. // the QuickDraw 3D exit function to clean up QuickDraw 3d.
  75.  
  76. void main(void)
  77. {
  78.     TQ3Status    myStatus;
  79.     Rect        rBounds = { 50, 50, 350, 350 } ;
  80.     Str255        title = "\pSpinning Box" ;
  81.     FSSpec        theFileSpec ;                // the file we are opening
  82.  
  83.     InitToolbox() ;
  84.     
  85.  
  86.     if(MetafileFileSpecify( &theFileSpec )) {
  87.     
  88.         SetCursor(*(GetCursor(watchCursor)));
  89.         
  90.         //    Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
  91.         myStatus = Q3Initialize();
  92.         if ( myStatus == kQ3Failure )
  93.             DebugStr("\pErInitialize returned failure.");            
  94.     
  95.         // install the error & warning handler - these get called whenever
  96.         // errors or warnings occur, which means we don't have to check so 
  97.         // much
  98.         Q3Error_Register( MyErrorHandler, 0L );        
  99.         Q3Warning_Register( MyWarningHandler, 0L );        
  100.     
  101.         // set up our globals
  102.         gQuitFlag = false ;
  103.         gMainWindow = NewCWindow(nil,&rBounds,title,false,noGrowDocProc,(WindowPtr)-1,true,0) ;
  104.  
  105.         // initialise our document structure
  106.         InitDocumentData( &gDocument ) ;
  107.         
  108.         // try to read the file into the main display group
  109.         if((gDocument.fModel = MyNewModelFromFile(&theFileSpec)) != NULL ) {        
  110.         
  111.             // get a bg picturre
  112.             if(PictureFileSpecify(&theFileSpec)) {
  113.                 PicHandle thePicture ;
  114.                 if((thePicture = OpenPICTFile( &theFileSpec )) != nil ) {
  115.                     
  116.                     CGrafPtr    savedPort ;
  117.                     GDHandle    gdh ;
  118.                     OSErr        theErr ;
  119.                     Rect        bounds = (**thePicture).picFrame ;
  120.                     
  121.                     GetGWorld( &savedPort, &gdh );
  122.                     
  123.                     // create the offscreen for the picture, this is faster than
  124.                     // calling DrawPicture each time through our update onscreen routine.
  125.                     theErr = NewGWorld(&gDocument.fBgPicture, 32, &bounds,nil,nil,0L);
  126.                     if(theErr != noErr )
  127.                         ExitToShell() ;
  128.                         
  129.                     SetGWorld( gDocument.fBgPicture, nil ) ;
  130.                     DrawPicture( thePicture, &bounds ) ;
  131.                     KillPicture( thePicture ) ;
  132.                     
  133.                     // clear our compositing buffer    
  134.                     theErr = NewGWorld(&gDocument.fCompositeBuffer, 32, &bounds,nil,nil,0L);
  135.                     if(theErr != noErr )
  136.                         ExitToShell() ;
  137.                         
  138.                     SetGWorld( gDocument.fCompositeBuffer, nil ) ;
  139.                     RGBBackColor( &kClearColor ) ;
  140.                     EraseRect(  &bounds ) ;
  141.                     
  142.                     // restore the environment                
  143.                     SetGWorld( savedPort, gdh );
  144.  
  145.                     AdjustCamera(    &gDocument,
  146.                                     (bounds.right - bounds.left),
  147.                                     (bounds.bottom - bounds.top) ) ;
  148.         
  149.                     SetWTitle( gMainWindow, theFileSpec.name );
  150.                     
  151.                     SizeWindow(    gMainWindow,
  152.                                 (bounds.right - bounds.left),
  153.                                 (bounds.bottom - bounds.top),
  154.                                 false );
  155.                                 
  156.                     ShowWindow( gMainWindow ) ;
  157.                     SetPort( gMainWindow ) ;
  158.             
  159.                     SetCursor(&qd.arrow) ;
  160.                     MainEventLoop();
  161.                 }
  162.             }
  163.             
  164.         }
  165.                         
  166.         //    Close our connection to the QuickDraw 3D library
  167.         myStatus = Q3Exit();
  168.         if ( myStatus == kQ3Failure )
  169.             DebugStr("\pErExit returned failure.");
  170.     }    
  171. }
  172.  
  173. //-------------------------------------------------------------------------------------------
  174. //
  175.  
  176. void InitDocumentData( DocumentPtr theDocument ) 
  177. {
  178.     GWorldPtr        theOffscreen ;
  179.     GDHandle        theDevice ;
  180.     TQ3Point3D        myOrigin = { 0, 0, 0 } ;
  181.     
  182.     // create a GWorld the size of the window area
  183.     OSErr myErr = NewGWorld(    &theDocument->fGWorld,
  184.                                 32,
  185.                                 &gMainWindow->portRect,
  186.                                 nil,
  187.                                 nil,
  188.                                 0L );
  189.     
  190.     if(myErr != noErr )
  191.         goto bail ;
  192.         
  193.     GetGWorld( &theOffscreen, &theDevice ) ;
  194.     SetGWorld( theDocument->fGWorld, nil ) ;
  195.     EraseRect( &gMainWindow->portRect ) ;
  196.     SetGWorld( theOffscreen, theDevice ) ;
  197.     
  198.     // sets up the 3d data for the scene
  199.     //    Create view for QuickDraw 3D.
  200.     theDocument->fView = MyNewView( theDocument->fGWorld );
  201.  
  202.     // the main display group:
  203.     theDocument->fModel = NULL ;
  204.     
  205.     // scale and group center
  206.     theDocument->fGroupScale = 1;                
  207.     theDocument->fGroupCenter = myOrigin ;    
  208.     
  209.     // the drawing styles:
  210.     theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  211.     theDocument->fBackFacing = Q3BackfacingStyle_New( kQ3BackfacingStyleBoth ) ;
  212.     theDocument->fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled ) ;
  213.  
  214.     // set the rotation matrix the identity matrix
  215.     Q3Matrix4x4_SetIdentity(&theDocument->fRotation);    
  216.                     
  217.     return ;
  218.     
  219. bail:
  220.     // we failed setting up the GWorld
  221.     // so we want to quit here
  222.     ExitToShell() ;
  223.     
  224. }
  225.  
  226. void DisposeDocumentData( DocumentPtr theDocument)
  227. {
  228.     if(theDocument->fView)
  229.         Q3Object_Dispose(theDocument->fView) ;                // the view for the scene
  230.  
  231.     if(theDocument->fModel)
  232.         Q3Object_Dispose(theDocument->fModel) ;                // object in the scene being modelled
  233.  
  234.     if(theDocument->fInterpolation)
  235.         Q3Object_Dispose(theDocument->fInterpolation) ;        // interpolation style used when rendering
  236.  
  237.     if(theDocument->fBackFacing)
  238.         Q3Object_Dispose(theDocument->fBackFacing) ;        // whether to draw shapes that face away from the camera
  239.  
  240.     if(theDocument->fFillStyle)
  241.         Q3Object_Dispose(theDocument->fFillStyle) ;            // whether drawn as solid filled object or decomposed to components
  242. }
  243. //-----------------------------------------------------------------------------
  244. // assumes the port is set up before being called
  245.  
  246. TQ3Status DocumentDraw3DData( DocumentPtr theDocument )
  247. {    
  248.     TQ3Status theStatus ;    
  249.  
  250.     //    Start rendering.
  251.     Q3View_StartRendering(theDocument->fView) ;
  252.     do {
  253.         theStatus = SubmitScene( theDocument ) ;
  254.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  255.  
  256.     return theStatus ;    
  257. }
  258.  
  259. //-------------------------------------------------------------------------------------------
  260. //
  261.  
  262. void DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect)
  263. {
  264.     if (theDocument->fGWorld) {
  265.     
  266.         CGrafPtr            savedPort;
  267.         GDHandle            savedDevice;
  268.         RGBColor            savedColor ;
  269.  
  270.         GetGWorld( &savedPort, &savedDevice);
  271.         // composite the image in the offscreen
  272.         // first draw the BG Pict
  273.         SetGWorld( theDocument->fCompositeBuffer,  nil);
  274.         
  275.         GetBackColor(&savedColor);
  276.         RGBBackColor(&kWhiteColor) ;
  277.                 
  278.         CopyBits ((BitMapPtr) &theDocument->fBgPicture->portPixMap,
  279.                   (BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  280.                   &theDocument->fBgPicture->portRect, 
  281.                   &theDocument->fCompositeBuffer->portRect, 
  282.                   srcCopy, 
  283.                   0L);
  284.         
  285.         RGBBackColor(&savedColor) ;
  286.         OpColor(&kClearColor);
  287.               
  288.         // next draw the 3d image over the bg pict using transparent copy
  289.         CopyBits ((BitMapPtr) &theDocument->fGWorld->portPixMap,
  290.                   (BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  291.                   &theDocument->fGWorld->portRect, 
  292.                   &theDocument->fCompositeBuffer->portRect, 
  293.                   srcCopy | transparent, 
  294.                   0L);
  295.  
  296.         SetGWorld( (CGrafPtr)gMainWindow,  nil);
  297.         
  298.         ClipRect( clipRect ) ;
  299.         
  300.         
  301.         // don't need to lockPixels on the GWorld as the 
  302.         // offscreen remains locked (see IM: QD3D), the
  303.         // pixmap for a pixmap draw context must remain locked
  304.         
  305.         CopyBits ((BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  306.                   &gMainWindow->portBits,
  307.                   &theDocument->fCompositeBuffer->portRect, 
  308.                   &gMainWindow->portRect,
  309.                   srcCopy, 
  310.                   0L);
  311.                   
  312.         SetGWorld( savedPort, savedDevice);
  313.       }
  314. }
  315.  
  316.  
  317. //-------------------------------------------------------------------------------------------
  318. //
  319.  
  320. short HiWrd(long aLong)
  321. {
  322.     return    (((aLong) >> 16) & 0xFFFF) ;
  323. }
  324.  
  325. //-------------------------------------------------------------------------------------------
  326. //
  327.  
  328. short LoWrd(long aLong)
  329. {
  330.     return    ((aLong) & 0xFFFF) ;
  331.  
  332. }
  333.  
  334. //-------------------------------------------------------------------------------------------
  335. //
  336.  
  337. void InitToolbox()
  338. {
  339.     Handle        menuBar = nil;
  340.  
  341.     MaxApplZone() ;
  342.     MoreMasters() ; MoreMasters() ; MoreMasters() ; 
  343.     
  344.     InitGraf( &qd.thePort );
  345.     InitFonts();
  346.     InitWindows();
  347.  
  348.     FlushEvents( everyEvent, 0 ) ;
  349.     // initialize application globals
  350.     
  351.     gQuitFlag = false;
  352.     InitCursor();
  353.     
  354. }
  355.  
  356. //-------------------------------------------------------------------------------------------
  357. //
  358. void MainEventLoop()
  359. {
  360.     EventRecord     event;
  361.     WindowPtr       window;
  362.     short           thePart;
  363.     Rect            screenRect, updateRect;
  364.     Point            aPoint = {100, 100};
  365.     
  366.  
  367.     while( !gQuitFlag )
  368.     {
  369.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  370.         {
  371.  
  372.             switch (event.what) {
  373.                 case mouseDown:
  374.                 
  375.                     thePart = FindWindow( event.where, &window );
  376.                     
  377.                     switch( thePart ) {
  378.                         case inMenuBar: 
  379.                             break;
  380.                         
  381.                         case inDrag:
  382.                     
  383.                             screenRect = (**GetGrayRgn()).rgnBBox;
  384.                             DragWindow( window, event.where, &screenRect );
  385.                             break ;
  386.                     
  387.                         case inContent:
  388.                     
  389.                             if (window != FrontWindow())
  390.                                 SelectWindow( window );
  391.                             break ;
  392.                     
  393.                         case inGoAway:
  394.                             if (TrackGoAway( window, event.where )) {
  395.                                 DisposeWindow ( window );
  396.                                 DisposeDocumentData( &gDocument ) ;
  397.                                 gQuitFlag = true;
  398.  
  399.                             }
  400.                             break ;
  401.                             
  402.                         default:
  403.                             break ;
  404.                     }
  405.                     break ;
  406.                             
  407.                         
  408.                 case updateEvt:
  409.                 
  410.                     window = (WindowPtr)event.message;
  411.                     updateRect = (**(window->visRgn)).rgnBBox;
  412.                     SetPort( window ) ;
  413.                     BeginUpdate( window );
  414.                     DocumentDraw3DData( &gDocument ) ;
  415.                     DocumentDrawOnscreen( &gDocument, &updateRect ) ;
  416.                     EndUpdate( window );
  417.  
  418.                     break ;
  419.                     
  420.                 case keyDown:
  421.                 case autoKey:
  422.                     HandleKeyPress(&event);
  423.                     break;
  424.                     
  425.                 case diskEvt:
  426.                     if ( HiWrd(event.message) != noErr ) 
  427.                         (void) DIBadMount(aPoint, event.message);
  428.                     break;
  429.                     
  430.                 case osEvt:
  431.                 case activateEvt:
  432.                     break;
  433.  
  434.  
  435.             }
  436.         }
  437.         else {
  438.             // we received a null event, rotate the cube
  439.             TQ3Matrix4x4    tmp;
  440.             Rect        theRect = ((GrafPtr)gMainWindow)->portRect ;
  441.             
  442.             SetPort((GrafPtr)gMainWindow) ;
  443.             Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
  444.             Q3Matrix4x4_Multiply(&gDocument.fRotation, &tmp, &gDocument.fRotation);
  445.  
  446.             InvalRect( &theRect ) ;
  447.         }
  448.     }
  449. }
  450.  
  451.  
  452. //-------------------------------------------------------------------------------------------
  453. //
  454. void HandleKeyPress(EventRecord *event)
  455. {}
  456.  
  457. //-------------------------------------------------------------------------------------------
  458. //
  459.  
  460.  
  461.  
  462.